<template>
    <el-dialog :visible.sync="v"
               :title="termTitle"
               @opened="doOpened"
               @open="doOpen"
               @close="doClose"
               width="70%"
               center
    >
        <div ref="terminal" class="felix-xterm"></div>
        <div slot="footer" class="dialog-footer">
            <el-button @click="v = false" >失败</el-button>
            <el-button @click="doChangeStatus" type="primary">成功</el-button>
        </div>
    </el-dialog>
</template>

<script>
    import {Terminal} from "xterm";
    import * as fit from "xterm/lib/addons/fit/fit";
    import * as webLinks from "xterm/lib/addons/webLinks/webLinks";
    import * as search from "xterm/lib/addons/search/search";
    import "xterm/dist/xterm.css"
    import infoList from '@/mixins/infoList'
    import {
        updateServerByIdAndStatus,
    }from "@/api/cmdb_server";
    let bindTerminalResize = (term, websocket) => {
        let onTermResize = size => {
            websocket.send(
                JSON.stringify({
                    type: "resize",
                    rows: size.rows,
                    cols: size.cols,
                })
            );
        };
        // register resize event.
        term.on("resize", onTermResize);
        // unregister resize event when WebSocket closed.
        websocket.addEventListener("close", function () {
            term.off("resize", onTermResize);
        });
    };
    let bindTerminal = (term, websocket, bidirectional, bufferedTime) => {
        term.write('\r\nWelcome to Felix Web Ssh Terminal\n\r\n');
        term.socket = websocket;
        let messageBuffer = null;
        let handleWebSocketMessage = function (ev) {
            if (bufferedTime && bufferedTime > 0) {
                if (messageBuffer) {
                    messageBuffer += ev.data;
                } else {
                    messageBuffer = ev.data;
                    setTimeout(function () {
                        term.write(messageBuffer);
                    }, bufferedTime);
                }
            } else {
                term.write(ev.data);
            }
        };

        let handleTerminalData = function (data) {
            websocket.send(
                JSON.stringify({
                    type: "cmd",
                    cmd: Base64.encode(data) // encode data as base64 format
                })
            );
        };

        websocket.onmessage = handleWebSocketMessage;
        if (bidirectional) {
            term.on("data", handleTerminalData);
        }

        // send heartbeat package to avoid closing webSocket connection in some proxy environmental such as nginx.
        let heartBeatTimer = setInterval(function () {
            websocket.send(JSON.stringify({type: "heartbeat", data: ""}));
        }, 20 * 1000);

        websocket.addEventListener("close", function () {
            websocket.removeEventListener("message", handleWebSocketMessage);
            term.off("data", handleTerminalData);
            delete term.socket;
            clearInterval(heartBeatTimer);
        });
    };
    export default {
        props: {obj: {type: Object, require: true}, visible: Boolean},
        name: "CompAnsibleInit",
        mixins: [infoList],
        data() {
            return {
                status: this.obj.status,
                searchKey: "",
                v: this.visible,
                term: null,
                ws: null,
                thisV: this.visible
            };
        },
        watch: {
            visible(val) {
                this.v = val;//新增result的watch，监听变更并同步到myResult上
            }
        },
        computed: {
            termTitle() {
                return `初始化服务器:${this.obj.virtual_name}`
            },
            wsUrl() {
                let userData = localStorage.getItem("vuex");
                let uuid = JSON.parse(userData).user.userInfo.uuid
                let url = (location.protocol === "http:" ? "ws" : "wss") + "://" + location.hostname + ":8081" + "/ansible/host/initWs";
                return `${url}?Id=${this.obj.ID}&uuid=${uuid}`
            }
        },
        created() {
        },
        methods: {
            onWindowResize() {
                this.term.fit(); // it will make terminal resized.
            },
            doLink(ev, url) {
                if (ev.type === 'click') {
                    window.open(url)
                }
            },
            doClose() {
                if (this.ws) {
                    this.ws.close()
                }
                if (this.term) {
                    this.term.dispose()
                }
                this.$emit('afterClose')
            },
            doOpen() {
            },
            doChangeStatus() {
                let id = this.obj.ID;
                let status = "1";
                updateServerByIdAndStatus({ 'id':id,'status':status }).then(res => {
                    if (res.code == 0) {
                        this.$message({
                            type: 'success',
                            message: '服务器初始化成功',
                        })
                        this.v = false;
                    }
                });
            },
            doOpened() {
                Terminal.applyAddon(fit);
                Terminal.applyAddon(webLinks);
                Terminal.applyAddon(search);
                //TODO 网页终端添加搜索功能
                this.term = new Terminal({
                    disableStdin: true,
                    fontSize: 18,
                    cursorBlink: true,
                    cursorStyle: 'bar',
                    bellStyle: "sound",
                });
                this.term.open(this.$refs.terminal);
                this.term.fit(); // first resizing
                this.term.webLinksInit(this.doLink);
                window.addEventListener("resize", this.onWindowResize);
                this.ws = new WebSocket(this.wsUrl);
                // this.ws.onclose = (ce) => {
                //     this.term.setOption("cursorBlink", false);
                //     if (ce.code !== 1005) {
                //         this.$notify.error({
                //             title: `code ${ce.code}`,
                //             message: ce.reason,
                //         });
                //         this.doClose();
                //     }
                // };
                bindTerminal(this.term, this.ws, true, -1);
                bindTerminalResize(this.term, this.ws);
                // term.on("resize", this.onTerminalResize);
            },
        },
    }
</script>

<style>
.cancelButton{
    padding: 12px 17px!important;
    border-right: none;
}

</style>
